package ltd.jdsoft.cute.httpclient;

import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ltd.jdsoft.cute.httpclient.exception.HttpClientInvokeException;
import ltd.jdsoft.cute.httpclient.model.HttpResponse;

/**
 * @Title: HttpInvoker.java
 * @Description: Http调用执行器
 * @author zhengzhq E-Mail:zzq0324@qq.com
 * @date 2017年5月5日 下午4:24:02
 */
public class HttpInvoker {

  private static Logger logger = LoggerFactory.getLogger(HttpInvoker.class);

  public static HttpResponse doGet(String url) {
    HttpGet get = null;
    try {
      get = new HttpGet(new URIBuilder(url).build());

      return invoke(get);
    } catch (Exception e) {
      throw new HttpClientInvokeException(e);
    }
  }

  public static HttpResponse doPost(String url, List<NameValuePair> paramList)
      throws RuntimeException {
    try {
      HttpPost post = new HttpPost(new URIBuilder(url).build());
      if (paramList != null && !paramList.isEmpty()) {
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "UTF-8");
        post.setEntity(entity);
      }

      return invoke(post);
    } catch (Exception e) {
      throw new HttpClientInvokeException(e);
    }
  }

  public static HttpResponse doPost(String url, String entityString) throws RuntimeException {
    try {
      HttpPost post = new HttpPost(new URIBuilder(url).build());
      post.setEntity(new ByteArrayEntity(entityString.getBytes("UTF-8")));

      return invoke(post);
    } catch (Exception e) {
      throw new HttpClientInvokeException(e);
    }
  }

  public static HttpResponse doPostJson(String url, String jsonString) throws RuntimeException {
    try {
      HttpPost post = new HttpPost(new URIBuilder(url).build());
      StringEntity entity = new StringEntity(jsonString, "UTF-8"); // 解决中文乱码问题
      entity.setContentType("application/json");
      post.setEntity(entity);

      return invoke(post);
    } catch (Exception e) {
      throw new HttpClientInvokeException(e);
    }
  }

  private static HttpResponse invoke(HttpRequestBase requestBase) throws Exception {
    CloseableHttpResponse response = null;
    try {
      response = HttpComponentsRequestFactory.getHttpClient().execute(requestBase);

      HttpResponse httpResponse = new HttpResponse();
      int statusCode = response.getStatusLine().getStatusCode();
      httpResponse.setCode(statusCode);

      if (statusCode == HttpStatus.SC_OK) {
        HttpEntity entity = response.getEntity();
        httpResponse.setResponse(EntityUtils.toString(entity, "UTF-8"));
      } else {
        logger.error("response http status code[{}] from url '{}'.", statusCode,
            requestBase.getURI().toURL());

        if (statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
          String url = response.getFirstHeader("Location").getValue();
          httpResponse.setRedirectUrl(url);
        }
      }

      return httpResponse;
    } catch (Exception e) {
      if (response != null) {
        EntityUtils.consume(response.getEntity());
      }
      // 出错的时候看请求是否中断，没中断的话立马中断，避免长时间的等待导致连接池耗完
      if (!requestBase.isAborted()) {
        requestBase.abort();
      }
      logger.error("httpclient invoke error from url: " + requestBase.getURI().toURL(), e);
      throw e;
    } finally {
      HttpClientUtils.closeQuietly(response);
    }
  }
}
